import Engine from '../engine/Engine';
import EventKernel from '../kernel/EventKernel';
import IdGenerator from '../kernel/IdGenerator';
import { ShaderType } from '../shaders';
import { BaseLayout } from '../typings/StyleType';
import SceneConfig, { SceneType } from './SceneType';

interface AbstractLayout {
    visible?: boolean;
    opacity?: number;
}

abstract class AbstractScene<
    L extends BaseLayout = BaseLayout,
> extends EventKernel {
    private readonly _id: string = IdGenerator.getId();
    private _type: SceneType;
    private _shaderName: ShaderType;
    private _order: number;
    protected _layout: L;
    protected _engine?: Engine;

    constructor(type: SceneType, layout: L) {
        super();
        this._type = type;
        const { order, shaderName } = SceneConfig[type];
        this._order = order;
        this._shaderName = shaderName;
        this._layout = layout;
    }

    getLayout() {
        return this._layout;
    }

    getOrder() {
        return this._order;
    }

    setOrder(order: number) {
        this._order = order;
    }

    getType() {
        return this._type;
    }

    getShaderName() {
        return this._shaderName;
    }

    getEngine() {
        return this._engine;
    }

    get id() {
        return this._id;
    }

    onAdd(engine: Engine) {
        const isHasAdd = Boolean(this._engine);
        this._engine = engine;
        if (!isHasAdd) {
            this._update();
        }
    }

    onRemove() {
        this.clear();
        delete this._engine;
    }

    abstract clear(): void;

    abstract setLayout(layout: AbstractLayout): void;

    protected abstract _update(): void;
}

export default AbstractScene;
